package rifl.meres4.commands;

import org.eclipse.osgi.framework.console.CommandInterpreter;
import org.eclipse.osgi.framework.console.CommandProvider;
import org.osgi.service.log.LogService;

import rifl.meres4.commons.model.Software;
import rifl.meres4.commons.step.IWorkflowStep;
import rifl.meres4.development.step.IArchitectureStep;
import rifl.meres4.development.step.IImplementationStep;
import rifl.meres4.development.step.IIntegrationStep;
import rifl.meres4.development.step.ISpecificationStep;
import rifl.meres4.development.step.IUIImplementationStep;
import rifl.meres4.release.step.IReleaseStep;
import rifl.meres4.release.step.IRepairStep;
import rifl.meres4.release.step.ITestStep;
import rifl.meres4.release.step.impl.TestStep;

public class DevelopmentCommandProvider implements CommandProvider {

	private ISpecificationStep specificationStep;
	private IArchitectureStep architectureStep;
	private IImplementationStep implementationStep;
	private IUIImplementationStep uiImplementationStep;
	private IIntegrationStep integrationStep;
	private ITestStep testStep;
	private IRepairStep repairStep;
	private IReleaseStep releaseStep;
	
	protected LogService log;
	
	protected Software commandDoStep(IWorkflowStep step)
	{
		Software software;
		try {
			software = step.get();
			if (software != null) {
				step.doStep(software);
				step.put(software);
			}
			return software;
		} catch (Exception e) {
			if (log != null) {
				log.log(LogService.LOG_ERROR, "Exception when executing step: " + getClass().getName() + ": " + e.getMessage());				
			} else {
				System.out.println("Exception when executing step: " + getClass().getName() + ": " + e.getMessage());
			}
		}
		return null;
	}
	
	@Override
	public String getHelp() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("---Software Development Workflow Control Commands---\n");
		buffer.append("\tstate - check if first step is available\n");
		buffer.append("\tspeci - Perform a Specification step\n");
		buffer.append("\tarchi - Perform an Architecture step\n");
		buffer.append("\timpl - Perform an Implementation step\n");
		buffer.append("\tuiimpl - Perform a UI Implementation step\n");
		buffer.append("\tintegr - Perform an Integration step\n");
		buffer.append("\ttest <boolean> - Perform a Test step. Argument 1 = 'true' --> tests successful\n");
		buffer.append("\trepair - Perform a Repair step\n");
		buffer.append("\trel - Perform a Release step\n");
		return buffer.toString();
	}	
	
	public void _state(CommandInterpreter ci) {
		if (specificationStep == null) {
			ci.println("SpecificationStep unavailable!");
		} else {
			ci.println("SpecificationStep available!");	
		}
	}
	
	/**
	 * Commands to control the workflow
	 */
	
	public void _speci(CommandInterpreter ci) {
		if(this.specificationStep != null)
		{
			if(this.specificationStep.hasInput())
			{
				Software result = commandDoStep(specificationStep);
				ci.println("1. Specification step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Soecification step!");
			}
		}
		else
		{
			ci.println("Specification service not available!");
		}
	}
	
	public void _archi(CommandInterpreter ci) {
		if(this.architectureStep != null)
		{
			if(this.architectureStep.hasInput())
			{
				Software result = commandDoStep(architectureStep);
				ci.println("2. Architecture design step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Architecture step!");
			}
		}
		else
		{
			ci.println("Architecture service not available!");
		}
	}
	
	public void _impl(CommandInterpreter ci) {
		if(this.implementationStep != null)
		{
			if(this.implementationStep.hasInput())
			{
				Software result = commandDoStep(implementationStep);
				ci.println("3a. Class Implementation step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Class Implementation step!");
			}
		}
		else
		{
			ci.println("Implementation service not available!");
		}
	}
	
	public void _uiimpl(CommandInterpreter ci) {
		if(this.uiImplementationStep != null)
		{
			if(this.uiImplementationStep.hasInput())
			{
				Software result = commandDoStep(uiImplementationStep);
				ci.println("3b. UI Implementation step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for UI Implementation step!");
			}
		}
		else
		{
			ci.println("UI Implementation service not available!");
		}
	}
	
	public void _integr(CommandInterpreter ci) {
		if(this.integrationStep != null)
		{
			if(this.integrationStep.hasInput())
			{
				Software result = commandDoStep(integrationStep);
				ci.println("4. Integration step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Integration step!");
			}
		}
		else
		{
			ci.println("Integration service not available!");
		}
	}
	
	public void _test(CommandInterpreter ci) {
		//The first argument should be "true" if tests were successful.
		//Usage: test true
		String arg = ci.nextArgument();
		if (arg == null || arg.isEmpty()) {
			ci.println("Provide one boolean argument for test step!");
			return;
		}
		if(this.testStep != null)
		{
			if(arg.equalsIgnoreCase("true"))
			{				
				testStep.setTestSuccess(true);
			}
			else
			{				
				testStep.setTestSuccess(false);
			}
		
		
			if(this.testStep.hasInput())
			{
				Software result = commandDoStep(testStep);
				ci.println("5. Test step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Test step!");
			}
		}
		else
		{
			ci.println("Test service not available!");
		}
	}
	
	public void _repair(CommandInterpreter ci) {
		if(this.repairStep != null)
		{
			if(this.repairStep.hasInput())
			{
				Software result = commandDoStep(repairStep);
				ci.println("5e. Repair step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Repair step!");
			}
		}
		else
		{
			ci.println("Repair service not available!");
		}
	}
	
	public void _rel(CommandInterpreter ci) {
		if(this.releaseStep != null)
		{
			if(this.releaseStep.hasInput())
			{
				Software result = commandDoStep(releaseStep);
				ci.println("6. Release step executed! Result: " + result.toString());
			}
			else
			{
				ci.println("No input for Release step!");
			}
		}
		else
		{
			ci.println("Release service not available!");
		}
	}
	
	/**
	 * End of commands
	 */
	
	public void setSpecificationStep(ISpecificationStep step) {
		this.specificationStep = step;
	}
	
	public void unsetSpecificationStep(ISpecificationStep step) {
		this.specificationStep = null;
	}
	
	public void setArchitectureStep(IArchitectureStep step) {
		this.architectureStep = step;
	}
	
	public void unsetArchitectureStep(IArchitectureStep step) {
		this.architectureStep = null;
	}
	
	public void setImplementationStep(IImplementationStep step) {
		this.implementationStep = step;
	}
	
	public void unsetImplementationStep(IImplementationStep step) {
		this.implementationStep = null;
	}
	
	public void setUIImplementationStep(IUIImplementationStep step) {
		this.uiImplementationStep = step;
	}
	
	public void unsetUIImplementationStep(IUIImplementationStep step) {
		this.uiImplementationStep = null;
	}
	
	public void setIntegrationStep(IIntegrationStep step) {
		this.integrationStep = step;
	}
	
	public void unsetIntegrationStep(IIntegrationStep step) {
		this.integrationStep = null;
	}
	
	public void setTestStep(ITestStep step) {
		this.testStep = step;
	}
	
	public void unsetTestStep(ITestStep step) {
		this.testStep = null;
	}
	
	public void setRepairStep(IRepairStep step) {
		this.repairStep = step;
	}
	
	public void unsetRepairStep(IRepairStep step) {
		this.repairStep = null;
	}
	
	public void setReleaseStep(IReleaseStep step) {
		this.releaseStep = step;
	}
	
	public void unsetReleaseStep(IReleaseStep step) {
		this.releaseStep = null;
	}

}
